package co.pushmall.modules.shop.service.impl;

import cn.hutool.core.util.ObjectUtil;
import co.pushmall.exception.BadRequestException;
import co.pushmall.modules.shop.domain.PushMallStoreCategory;
import co.pushmall.modules.shop.domain.PushMallStoreProduct;
import co.pushmall.modules.shop.repository.PushMallStoreCategoryRepository;
import co.pushmall.modules.shop.repository.PushMallStoreProductRepository;
import co.pushmall.modules.shop.service.PushMallStoreCategoryService;
import co.pushmall.modules.shop.service.dto.PushMallStoreCategoryDTO;
import co.pushmall.modules.shop.service.dto.PushMallStoreCategoryQueryCriteria;
import co.pushmall.modules.shop.service.mapper.PushMallStoreCategoryMapper;
import co.pushmall.utils.FileUtil;
import co.pushmall.utils.PageUtil;
import co.pushmall.utils.QueryHelp;
import co.pushmall.utils.ValidationUtil;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author pushmall
 * @date 2019-10-03
 */
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class PushMallStoreCategoryServiceImpl implements PushMallStoreCategoryService {

    private final PushMallStoreCategoryRepository pushMallStoreCategoryRepository;
    private final PushMallStoreProductRepository pushMallStoreProductRepository;

    private final PushMallStoreCategoryMapper pushMallStoreCategoryMapper;

    public PushMallStoreCategoryServiceImpl(PushMallStoreCategoryRepository pushMallStoreCategoryRepository,
                                            PushMallStoreProductRepository pushMallStoreProductRepository,
                                            PushMallStoreCategoryMapper pushMallStoreCategoryMapper) {
        this.pushMallStoreCategoryRepository = pushMallStoreCategoryRepository;
        this.pushMallStoreProductRepository = pushMallStoreProductRepository;
        this.pushMallStoreCategoryMapper = pushMallStoreCategoryMapper;
    }

    @Override
    public void download(List<PushMallStoreCategoryDTO> queryAll, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (PushMallStoreCategoryDTO storeCategoryDTO : queryAll) {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("分类名称", storeCategoryDTO.getCateName());
            map.put("分类状态", storeCategoryDTO.getIsShow() == 1 ? "启用" : "停用");
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    @Override
    public Map<String, Object> queryAll(PushMallStoreCategoryQueryCriteria criteria, Pageable pageable) {
        Page<PushMallStoreCategory> page = pushMallStoreCategoryRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder), pageable);
        return PageUtil.toPage(page.map(pushMallStoreCategoryMapper::toDto));
    }

    @Override
    public List<PushMallStoreCategoryDTO> queryAll(PushMallStoreCategoryQueryCriteria criteria) {
        return pushMallStoreCategoryMapper.toDto(pushMallStoreCategoryRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder)));
    }

    @Override
    public PushMallStoreCategoryDTO findById(Integer id) {
        Optional<PushMallStoreCategory> yxStoreCategory = pushMallStoreCategoryRepository.findById(id);
        //ValidationUtil.isNull(yxStoreCategory,"PushMallStoreCategory","id",id);
        if (yxStoreCategory.isPresent()) {
            return pushMallStoreCategoryMapper.toDto(yxStoreCategory.get());
        }
        return new PushMallStoreCategoryDTO();
    }

    @Override
    public PushMallStoreCategoryDTO findByName(String name) {
        return null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public PushMallStoreCategoryDTO create(PushMallStoreCategory resources) {
        if (ObjectUtil.isNull(resources.getPid())) {
            resources.setPid(0);
        }
        if (ObjectUtil.isNull(resources.getSort())) {
            resources.setSort(1);
        }
        return pushMallStoreCategoryMapper.toDto(pushMallStoreCategoryRepository.save(resources));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(PushMallStoreCategory resources) {
        if (resources.getId().equals(resources.getPid())) {
            throw new BadRequestException("自己不能选择自己哦");
        }
        Optional<PushMallStoreCategory> optionalPushMallStoreCategory = pushMallStoreCategoryRepository.findById(resources.getId());
        ValidationUtil.isNull(optionalPushMallStoreCategory, "PushMallStoreCategory", "id", resources.getId());
        PushMallStoreCategory pushMallStoreCategory = optionalPushMallStoreCategory.get();
        pushMallStoreCategory.copy(resources);
        pushMallStoreCategoryRepository.save(pushMallStoreCategory);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Integer id) {
        PushMallStoreCategory storeCategory = pushMallStoreCategoryRepository.findByPid(id);

        if (storeCategory != null) {
            throw new BadRequestException("请先删除子类");
        }
        PushMallStoreCategory category = new PushMallStoreCategory();
        category.setId(id);
        List<PushMallStoreProduct> storeProduct = pushMallStoreProductRepository.findByStoreCategoryAndIsDel(category, 0);

        if (!storeProduct.isEmpty()) {
            throw new BadRequestException("此分类下有商品,不能删除");
        }

        pushMallStoreCategoryRepository.delCategory(id);
    }


    @Override
    public Object buildTree(List<PushMallStoreCategoryDTO> categoryDTOS) {
        Set<PushMallStoreCategoryDTO> trees = new LinkedHashSet<>();
        Set<PushMallStoreCategoryDTO> cates = new LinkedHashSet<>();
        List<String> deptNames = categoryDTOS.stream().map(PushMallStoreCategoryDTO::getCateName)
                .collect(Collectors.toList());

        PushMallStoreCategoryDTO categoryDTO = new PushMallStoreCategoryDTO();
        Boolean isChild;
        List<PushMallStoreCategory> categories = pushMallStoreCategoryRepository.findAll();
        for (PushMallStoreCategoryDTO deptDTO : categoryDTOS) {
            isChild = false;
            if ("0".equals(deptDTO.getPid().toString())) {
                trees.add(deptDTO);
            }
            for (PushMallStoreCategoryDTO it : categoryDTOS) {
                if (it.getPid().equals(deptDTO.getId())) {
                    isChild = true;
                    if (deptDTO.getChildren() == null) {
                        deptDTO.setChildren(new ArrayList<PushMallStoreCategoryDTO>());
                    }
                    deptDTO.getChildren().add(it);
                }
            }
            if (isChild) {
                cates.add(deptDTO);
            }
            for (PushMallStoreCategory category : categories) {
                if (category.getId().equals(deptDTO.getPid()) && !deptNames.contains(category.getCateName())) {
                    cates.add(deptDTO);
                }
            }
        }


        if (CollectionUtils.isEmpty(trees)) {
            trees = cates;
        }


        Integer totalElements = categoryDTOS != null ? categoryDTOS.size() : 0;

        Map map = new HashMap();
        map.put("totalElements", totalElements);
        map.put("content", CollectionUtils.isEmpty(trees) ? categoryDTOS : trees);
        return map;
        //return null;
    }
}
